#include <GenericServerApp.h>
//#include <JabberSubsystem.h>
//#include <Network/NetworkSubsystem.h>
//#include <SMSSubsystem.h>
//#include <AuthenticationSubsystem.h>
//#include <Financial/FinancialSubsystem.h>
//#include <Database/DatabaseSubsystem.h>
//#include <UDTSubsystem.h>

#include <ApplicationStartingNotification.h>
#include <StopRootApplicationNotification.h>
#include <Poco/NotificationCenter.h>
#include <Poco/NObserver.h>
#include <Poco/FileChannel.h>
#include <Poco/Logger.h>
#include <Poco/Format.h>

#include "Poco/Util/ServerApplication.h"

#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>


#include <iostream>


using namespace Poco::Util;
GenericServerApp::GenericServerApp(void)
:iStopEvent("StopRootApplicationEvent")
,_helpRequested(false)
,iStopRunningServer(false)
{
}

GenericServerApp::~GenericServerApp(void)
{
}

void GenericServerApp::initialize(Application& self)
{
	loadConfiguration(); // load default configuration files, if present

	RegisterSubsystemClasses();
	// create subsystem
	//iSubSystemFactory.registerClass<UDTSubsystem>("UDTSubsystem");

	//iSubSystemFactory.registerClass<Database::DatabaseSubsystem>("DatabaseSubsystem");

	//iSubSystemFactory.registerClass<Jabber::JabberSubsystem>("JabberSubsystem");
	//iSubSystemFactory.registerClass<Authentication::AuthenticationSubsystem>("AuthenticationSubsystem");
	//iSubSystemFactory.registerClass<SMS::SMSSubsystem>("SMSSubsystem");
	//iSubSystemFactory.registerClass<Financial::FinancialSubsystem>("FinancialSubsystem");

	try
	{
		std::string aSubsystemKey = "RootApplication.subsystem";
		int aCount = 0;
		for (; ; aCount++)
		{
			std::string aKey = aSubsystemKey;
			if (aCount > 0)
			{
				aKey = "";
				Poco::format(aKey , "RootApplication.subsystem[%d]",aCount);
			}

			if (!config().hasOption(aKey))
				break;
			std::string aClass= config().getString(aKey);
			addSubsystem( iSubSystemFactory.createInstance(aClass) );
		}

	}
	catch (Poco::Exception& aEx)
	{
		
	}
	
	ServerApplication::initialize(self);
}

void GenericServerApp::uninitialize()
{
	ServerApplication::uninitialize();
}

void GenericServerApp::defineOptions(OptionSet& options)
{
	ServerApplication::defineOptions(options);

	options.addOption(
		Option("help", "h", "display help information on command line arguments")
		.required(false)
		.repeatable(false));

	options.addOption(
		Option("rootstop", "rootstop", "root stop")
		.required(false)
		.repeatable(false));
}

void GenericServerApp::handleOption(const std::string& name, const std::string& value)
{
	ServerApplication::handleOption(name, value);

	if (name == "help")
		_helpRequested = true;

	if (name == "rootstop")
		iStopRunningServer = true;
}

void GenericServerApp::displayHelp()
{
	HelpFormatter helpFormatter(options());
	helpFormatter.setCommand(commandName());
	helpFormatter.setUsage("OPTIONS");
	helpFormatter.setHeader("A web server that receive request (from SMS) and send it to jabber.");
	helpFormatter.format(std::cout);
}

void GenericServerApp::HandleStopRootApp(const Poco::AutoPtr<StopRootApplicationNotification>& aNotification)
{
	this->logger().information("HandleStopRootApp");
	logger().information(" notification key: "+aNotification->iStopApplicationKey);

	if (aNotification->iStopApplicationKey == "Quit By Jabber Subsystem" )
		iStopEvent.set();

}

int GenericServerApp::main(const std::vector<std::string>& args)
{
	if (_helpRequested)
	{
		displayHelp();
		return EXIT_OK;
	}
	if (iStopRunningServer)
	{
		iStopEvent.set();
		return EXIT_OK;
	}	
	
	std::string aLogPath = config().getString("loggerfilepath" , "");

	if (aLogPath.length())
	{
		std::cout<<aLogPath<<" is a logfile"<<std::endl;
		Poco::AutoPtr<Poco::FileChannel> aLogFileChannel = new Poco::FileChannel(aLogPath);
		Poco::Logger::setChannel("" , aLogFileChannel);
	}


	Poco::NotificationCenter::defaultCenter().postNotification( new ApplicationStartingNotification(*this) );
	Poco::NotificationCenter::defaultCenter().addObserver( Poco::NObserver<GenericServerApp , StopRootApplicationNotification>(*this ,&GenericServerApp::HandleStopRootApp )  );
	iStopEvent.wait();
	//waitForTerminationRequest();

	Poco::NotificationCenter::defaultCenter().removeObserver( Poco::NObserver<GenericServerApp , StopRootApplicationNotification>(*this ,&GenericServerApp::HandleStopRootApp )  );

	return EXIT_OK;
}

//


